﻿using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq;
using System.Text;

namespace WebSocketServer
{
    public static class Clients
    {
        private static object _lockObject = new object();
        public static ConcurrentDictionary<JiveClientSession, ChatClient> ConnectedClients { get; private set; }
        /// <summary>
        /// Dictionary with Username as key, with a value of a dictionary with ClientID as key and ChatClient as value.
        /// </summary>
        public static ConcurrentDictionary<string, ConcurrentDictionary<string, ChatClient>> ConnectedClientsByNameAndDeviceID { get; private set; }//key:username -> key:DeviceID, value:chatclient
        public static ConcurrentDictionary<string, ChatClient> ConnectedClientsByUserID { get; private set; }

        static Clients()
        {
            ConnectedClients = new ConcurrentDictionary<JiveClientSession, ChatClient>();
            ConnectedClientsByNameAndDeviceID = new ConcurrentDictionary<string, ConcurrentDictionary<string, ChatClient>>();
            ConnectedClientsByUserID = new ConcurrentDictionary<string, ChatClient>();
        }
        public static void AddConnectedClient(JiveClientSession info, ChatClient client)
        {
            var existingClientSession = ConnectedClients.FirstOrDefault(x => x.Value.UserID == client.UserID).Key;
            if (existingClientSession != null)
            {
                ChatClient oldClient;
                ConnectedClients.TryRemove(existingClientSession, out oldClient);
            }
            ConnectedClients[info] = client;
            if (!ConnectedClientsByNameAndDeviceID.ContainsKey(client.User.UserName))
                ConnectedClientsByNameAndDeviceID.GetOrAdd(client.User.UserName, new ConcurrentDictionary<string, ChatClient>());
            ConnectedClientsByNameAndDeviceID[client.User.UserName][client.DeviceID] = client;
            ConnectedClientsByUserID[client.UserID] = client;
        }
        public static bool RemoveConnectedClient(JiveClientSession info)
        {
            ChatClient cli;
            bool success = true;
            lock (_lockObject)
            {
                if (!ConnectedClients.TryRemove(info, out cli))
                    success = false;

                if (cli != null && !ConnectedClients.Any(x => x.Value.UserID == cli.UserID))
                {
                    if (ConnectedClientsByNameAndDeviceID.ContainsKey(cli.User.UserName) && !ConnectedClientsByNameAndDeviceID[cli.User.UserName].TryRemove(cli.DeviceID, out cli))
                        success = false;
                    if (cli != null)
                    {
                        if (!ConnectedClientsByUserID.TryRemove(cli.UserID, out cli))
                            success = false;
                    }
                }
            }
            return success;
        }


        public static JiveClientSession GetConnectionFromUserID(string UserID)
        {
            ChatClient client;
            if (ConnectedClientsByUserID.TryGetValue(UserID, out client))
            {
                return client.CurrentSession;
            }
            else
                return null;

        }



        public static IEnumerable<ChatClient> GetChatClientsFromUsername(string userName)
        {
            ConcurrentDictionary<string, ChatClient> dic;
            if (ConnectedClientsByNameAndDeviceID.TryGetValue(userName, out dic))
            {

                return dic.Values;
            }
            else
                return new List<ChatClient>();
        }
    }
}
